package com.lagou.config;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableRabbit
public class RabbitConfig {

  private static final Logger logger = LoggerFactory.getLogger(RabbitConfig.class);

  /**
   * 订单取消事件队列
   */
  @Bean
  public Queue oderCancelQueue() {
    Map<String, Object> props = new HashMap<>();
    props.put("x-message-ttl", 5_000);
    props.put("x-dead-letter-exchange", "ex.order.dlx");
    props.put("x-dead-letter-routing-key", "order.cancel.dlx");

    return new Queue("queue.order.cancel", true, false, false, props);
  }

  /**
   * 订单业务交换器
   */
  @Bean
  public Exchange orderExchange() {
    return new DirectExchange("ex.order", true, false);
  }

  /**
   * 死信交换器
   */
  @Bean
  public Exchange orderCancelDlxExchange() {
    return new DirectExchange("ex.order.dlx", true, false);
  }

  /**
   * 订单取消事件死信队列
   */
  @Bean
  public Queue orderCancelDlxQueue() {
    return new Queue("queue.order.cancel.dlx", true, false, false);
  }

  /**
   * 绑定订单取消队列
   *
   * @return
   */
  @Bean
  public Binding bindingOrderCancelQueue() {
    return BindingBuilder.bind(oderCancelQueue()).to(orderExchange()).with("order.cancel").noargs();
  }

  /**
   * 绑定订单取消死信队列
   *
   * @return
   */
  @Bean
  public Binding bindingOrderCancelDlxQueue() {
    return BindingBuilder.bind(orderCancelDlxQueue()).to(orderCancelDlxExchange()).with("order.cancel.dlx").noargs();
  }

  @Bean
  public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
    RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
    rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
    rabbitTemplate.setConfirmCallback((correlationData, flag, cause) -> {

      if (!flag) {
        try {
          logger.info("消息确认失败：{}", new String(correlationData.getReturnedMessage().getBody(), "UTF-8"));
          // TODO 更新补偿消息为确认失败，使用定时任务进行补偿重发
        } catch (UnsupportedEncodingException e) {
          logger.error("解码确认失败消息失败");
        }
      } else {
        // TODO 更新消息为确认成功
      }
    });
    return rabbitTemplate;
  }

}
